package mobi.zeedev.flyingsaucer.common.CredentialsModule.impl;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import mobi.zeedev.flyingsaucer.common.CredentialsModule.interfaces.ICredentials;
import org.apache.http.client.CookieStore;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class Credentials implements Serializable, ICredentials {

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Constants
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    public static String TAG = "Credentials";

    //Constant for login parameters/cookie
    public static final String HTTP_PARAM_F = "Login";

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Credentials Definition
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    // Login
/*	public static final String STORE_NUMBER = "storeNumber";
	public static final String CARD_NUMBER = "cardNumber";
	public static final String PASSWORD = "password";

	// Home
	public static final String PASSWORD_HASH = "passwordHash";
	public static final String USER_NAME = "username";
	public static final String MEMBER_ID = "memberId";

	//Internal DB stuff
	public static final String DB_ID = "_id";
	public static final String UFO_REMEMBER = "ufoRemember";
	public static final String UFO_AUTO_LOGIN = "ufoAutoLogin";
	public static final String UFO_ORIGIN_DATE = "originDate";*/

    //These are the old mappings so people dont lose their credentials when they login

    public static final String STORE_NUMBER = "storeId";
    public static final String CARD_NUMBER = "cardNumber";
    public static final String PASSWORD = "password";


    public static final String UFO_REMEMBER = "remember";
    public static final String UFO_AUTO_LOGIN = "autoLogon";
    public static final String UFO_ORIGIN_DATE = "originDate";
    public static final String UFO_MOU_MEMBER = "ufoMouMember";


    public static final String PASSWORD_HASH = "hash";
    public static final String USER_NAME = "user";
    public static final String MEMBER_ID = "memberID";


    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // State
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    private String storeNumber = null;
    private String cardNumber = null;
    private String password = null;

    private String passwordHash = null;
    private String username = null;
    private Integer memberId = null;

    private Integer dbId = null;
    private Boolean ufoRemember = null;
    private Boolean ufoAutoLogin = null;
    private Date originDate = null;
    private Boolean ufoMouMember = null;
    private Boolean ufoNonMember = null;

//    private CookieStore cookieStore = null;

//    public Boolean isBound = false;

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Constructors
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    @Inject
    public Credentials() {
        super();
        reset();
    }

    @Override
    public synchronized void reset() {
        storeNumber = "";
        cardNumber = "";
        password = "";

        passwordHash = "";
        username = "";
        memberId = 0;

        dbId = 0;
        ufoRemember = false;
        ufoAutoLogin = false;
        ufoMouMember = false;
        originDate = null;
        ufoNonMember = false;

//        cookieStore = new BasicCookieStore();
    }

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Generators
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    private static String getEscapedEmail(String in) {
        String ret = null;
        if (!isNullOrEmpty(in)) {
            ret = in.replace("@", "%40");
        }
//		if (!TextUtils.isEmpty(in)) {
//			ret = in.replace("@", "%40");
//		}
        //TODO ANDROID URI PROBLEM  / DEPENDENCY ISSUE
//        ret = Uri.encode(in);
        return ret;
    }

    @Override
    public synchronized List<Cookie> generateCookieInfo() {
        String[] cookieList = {
                // make sure to set this back before it's being published
                "card", this.getCardNumber(), "store", this.getStoreNumber(),
                "hash", this.getPasswordHash(), "user", getEscapedEmail(this.getUserName())
//				,
//				"user_logged_in", "true"
        };

        //TODO may need to clear this periodically??? could it fill up
        CookieStore cs = new BasicCookieStore();

        for (int i = 0; i < cookieList.length - 1; i = i + 2) {
            BasicClientCookie bcc = new BasicClientCookie(cookieList[i],
                    cookieList[i + 1]);
            bcc.setVersion(0);
            bcc.setDomain(".beerknurd.com");
            bcc.setPath("/");
            Calendar c = Calendar.getInstance();
            c.add(Calendar.YEAR, 1);
            bcc.setExpiryDate(c.getTime());
            cs.addCookie(bcc);
            // Log.d(TAG, bcc.toString());
        }

        return cs.getCookies();
    }

    @Override
    public synchronized Map<String, String> getLoginParams() {
        Map<String, String> m = new HashMap<String, String>(5);
        m.put("card_number", this.getCardNumber());
        m.put("password", this.getPassword());
        m.put("store", this.getStoreNumber());
        m.put("f", HTTP_PARAM_F);
        m.put("cookie", "true");
        if (this.ufoMouMember != null && this.ufoMouMember) {
            m.put("mou", "true");
        }
        return m;
    }

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Properties / Attributes (things that describe the state/condition of credentials)
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    @Override
    public synchronized Boolean isLoggedIn() {
        boolean res =
                           !isNullOrEmpty(this.password)
                        && !isNullOrEmpty(this.storeNumber)
                        && !isNullOrEmpty(this.username)
                        && !isNullOrEmpty(this.cardNumber);
        return res;
    }

    @Override
    public synchronized Boolean isLoginAvailable() {
        boolean res =
                !isNullOrEmpty(this.storeNumber)
                        && !isNullOrEmpty(this.cardNumber)
                        && !isNullOrEmpty(this.password);
        return res;
    }

    @Override
    public synchronized Boolean isDownloadPairComplete() {
        return isLoggedIn() && hasMemberId();
    }

    @Override
    public synchronized Boolean isMasterRefreshCompletedWithLogin() {
        return isLoggedIn() && hasMemberId() && hasOriginDate();
    }


    @Override
    public synchronized Boolean hasMemberId() {
        return !isNullOrEmpty(this.memberId);
    }

    @Override
    public synchronized Boolean hasOriginDate() {
        return !isNullOrEmpty(this.originDate);
    }

    @Override
    public synchronized Boolean permittedLogin() {
        return (getUfoAutoLogin()
                && (isLoggedIn() || isLoginAvailable())
                && getUfoRemember());
    }

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Utility
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    @Override
    public synchronized String toString() {
        return "Credentials [_ID=" + dbId + ", hash=" + passwordHash + ", loginAuto="
                + ufoAutoLogin + ", loginCard=" + cardNumber + ", loginPassword="
                + password + ", loginRemember=" + ufoRemember
                + ", loginStore=" + storeNumber + ", memberId=" + memberId
                + ", originDate=" + originDate + ", user=" + username + "]";
    }

    private static Boolean isNullOrEmpty(Object r) {
        return (r == null) ? true : r.toString().equals("");
    }

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Complex Getter/Setters
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    @Override
    public synchronized void setPassword(String loginPassword) {
        this.password = loginPassword;
        try {
            this.passwordHash = SHA1.getSHA1(this.password);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

/*    public synchronized CookieStore getCookieStore() {
        generateCookieInfo();
        return cookieStore;
    }

    public synchronized void setCookieStore(CookieStore cookieStore) {
        this.cookieStore = cookieStore;
    }*/

    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    // Simple Getter/Setters
    //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    @Override
    public synchronized void setUserName(String user) {
        this.username = user;
        //this.setHash(getSHA1(this.getLoginPassword()));
    }

    @Override
    public synchronized Integer getDBId() {
        return dbId;
    }

    @Override
    public synchronized String getPasswordHash() {
        return passwordHash;
    }

    @Override
    public synchronized Boolean getUfoAutoLogin() {
        return ufoAutoLogin;
    }

    @Override
    public synchronized String getCardNumber() {
        return cardNumber;
    }

    @Override
    public synchronized String getPassword() {
        return password;
    }

    @Override
    public synchronized Boolean getUfoRemember() {
        return ufoRemember;
    }

    @Override
    public synchronized String getStoreNumber() {
        return storeNumber;
    }

    @Override
    public synchronized Integer getMemberId() {
        return memberId;
    }

    @Override
    public synchronized Date getOriginDate() {
        return originDate;
    }

    @Override
    public synchronized String getUserName() {
        return username;
    }

    @Override
    public synchronized void setDBId(Integer id) {
        dbId = id;
    }

    @Override
    public synchronized void setPasswordHash(String hash) {
        this.passwordHash = hash;
    }

    @Override
    public synchronized void setUfoAutoLogin(Boolean loginAuto) {
        this.ufoAutoLogin = loginAuto;
    }

    @Override
    public synchronized void setCardNumber(String loginCard) {
        this.cardNumber = loginCard;
    }

    @Override
    public synchronized void setUfoRemember(Boolean loginRemember) {
        this.ufoRemember = loginRemember;
    }

    @Override
    public synchronized void setStoreNumber(String loginStore) {
        this.storeNumber = loginStore;
    }

    @Override
    public synchronized void setMemberId(Integer memberID) {
        this.memberId = memberID;
    }

    @Override
    public synchronized void setOriginDate(Date originDate) {
        this.originDate = originDate;
    }

    @Override
    public synchronized void setUfoMouMember(Boolean ufoMouMember) {
        this.ufoMouMember = ufoMouMember;
    }

    @Override
    public synchronized Boolean getUfoMouMember() {
        return this.ufoMouMember;
    }

    @Override
    public synchronized void setUfoNonMember(Boolean b) {
        this.ufoNonMember = b;
    }

    @Override
    public synchronized Boolean getUfoNonMember() {
        return this.ufoNonMember;
    }

/*    public synchronized void addCookiesToStore(List<Cookie> cookies) {
        for (Cookie cookie : cookies) {
            cookieStore.addCookie(cookie);
        }
    }*/


}
